package cc.rengu.redp.bizimpl.upmp.service.impl;

import cc.rengu.redp.bizimpl.constant.UpmpConstant;
import cc.rengu.redp.bizimpl.enums.UserStatusEnum;
import cc.rengu.redp.bizimpl.enums.UserTypeEnum;
import cc.rengu.redp.bizimpl.manager.UpmpUserManager;
import cc.rengu.redp.bizimpl.upmp.dao.UpmpUserInfoMapper;
import cc.rengu.redp.bizimpl.upmp.dao.UpmpUserRoleMapper;
import cc.rengu.redp.bizimpl.upmp.domain.*;
import cc.rengu.redp.bizimpl.upmp.service.*;
import cc.rengu.redp.bizimpl.upmp.vo.UpmpUserInfoVO;
import cc.rengu.redp.bizimpl.utils.CommonUtils;
import cc.rengu.redp.bizimpl.utils.GZIPUtils;
import cc.rengu.redp.common.domain.QueryRequest;
import cc.rengu.redp.common.exception.RedpException;
import cc.rengu.redp.common.properties.RedpProperties;
import cc.rengu.redp.common.utils.DateUtil;
import cc.rengu.redp.common.utils.HashUtil;
import cc.rengu.redp.common.utils.SortUtil;
import cc.rengu.redp.system.service.UserConfigService;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author System
 */
@Slf4j
@Service("upmpUserInfoService")
@DS("upmp")
public class UpmpUserInfoServiceImpl extends ServiceImpl<UpmpUserInfoMapper, UpmpUserInfo> implements IUpmpUserInfoService {

    @Autowired
    private UpmpUserRoleMapper upmpUserRoleMapper;
    @Autowired
    private UserConfigService userConfigService;
    @Autowired
    private IUpmpCacheService upmpCacheService;
    @Autowired
    private IUpmpUserRoleService upmpUserRoleService;
    @Autowired
    private UpmpUserManager upmpUserManager;
//    @Autowired
//    private SysWorkFlowService sysWorkFlowService;
    @Autowired
    private IUpmpRoleService upmpRoleService;

    @Autowired
    private IUpmpOrganizationService upmpOrganizationService;
//    @Autowired
//    private DeptService deptService;
    @Autowired
    private RedpProperties redpProperties;
    @Autowired
    private IUpmpSysParamService upmpSysParamService;


    @Override
    public UpmpUserInfo findByName(String username) {
        return baseMapper.selectOne(new LambdaQueryWrapper<UpmpUserInfo>().eq(UpmpUserInfo::getUserName, username));
//        return null;
    }

    @Override
    public UpmpUserInfo findById(String userId) {
        return baseMapper.selectById(userId);
    }



    /**
     * 通过用户id查找用户
     *
     * @param id 用户表id
     * @return user
     */
    @Override
    public UpmpUserInfoVO findVOById(String id){
        UpmpUserInfoVO vo = new UpmpUserInfoVO();
        UpmpUserInfo userInfo = findById(id);
        if(!ObjectUtils.isEmpty(userInfo)){
            BeanUtils.copyProperties(userInfo,vo);
        }
        return vo;
    }

    @Override
    public UpmpUserInfo findByUserId(String instId,String userId){
        UpmpUserInfo user = baseMapper.selectOne(new LambdaQueryWrapper<UpmpUserInfo>().eq(UpmpUserInfo::getInstId, instId).eq(UpmpUserInfo::getUserId, userId));
        return user;
    }
    @Override
    public UpmpUserInfo findByLoginId(String userType,String loginId){

        UpmpUserInfo user = baseMapper.findByLoginId(userType,loginId);
        return user;
    }
    @Override
    public IPage<UpmpUserInfoVO> findUserPage(UpmpUserInfoVO user, QueryRequest request) throws RedpException {

        Page<UpmpUserInfo> page = new Page<>();
        SortUtil.handlePageSort(request, page, "userId", UpmpConstant.ORDER_ASC, true);
        try {
            //防止点击重置按钮后不传法人行查询
            if(user.getInstId()==null) {
                UpmpSysParam defaultInst = upmpSysParamService.getById(UpmpConstant.DEAFULT_INST_PARAM_ID);
                List<UpmpSysParam> instList = upmpSysParamService.findChildrenByPrimaryKey(UpmpConstant.SYS_INST_PARAM, defaultInst.getInstId(), null);
                user.setInstId(instList.get(0).getInstId());
            }
            IPage<UpmpUserInfo> userIPage =  this.baseMapper.findPageList(page,user);
            List<UpmpUserInfo> userList = userIPage.getRecords();
            List<UpmpUserInfoVO> uservoList = Lists.newArrayList();
            userList.forEach(userItem -> {
                UpmpUserInfoVO vo = new UpmpUserInfoVO();
                BeanUtils.copyProperties(userItem,vo);
                //
                if (!StringUtils.isEmpty(userItem.getOrgCode())) {
                    UpmpOrganization org = null;
                    org = upmpOrganizationService.getOrgByCode(userItem.getOrgCode(),userItem.getInstId());
                    if (!ObjectUtils.isEmpty(org)) {
                        vo.setOrgId(org.getId());
                        vo.setOrgName(org.getOrgName());
                    }
                }

                //角色
                List<UpmpUserRole> userRoles = upmpUserRoleService.list(new LambdaQueryWrapper<UpmpUserRole>()
                        .eq(UpmpUserRole::getUserId, userItem.getId()));
                if(!ObjectUtils.isEmpty(userRoles)){
                    List<String> roleIds = userRoles.stream().map(it ->String.valueOf(it.getRoleId())).collect(Collectors.toList());
                    List<UpmpRole> roles = upmpRoleService.list(new LambdaQueryWrapper<UpmpRole>().in(UpmpRole::getId, roleIds));
                    List<String> roleNames = roles.stream().map(UpmpRole::getRoleName).collect(Collectors.toList());
                    vo.setRoleId(String.join(",", roleIds));
                    vo.setRoleName(String.join(",", roleNames));
                }
                uservoList.add(vo);
            });

            IPage<UpmpUserInfoVO> userVOIPage = new Page<UpmpUserInfoVO>();
            BeanUtils.copyProperties(userIPage,userVOIPage);
            userVOIPage.setRecords(uservoList);
            return userVOIPage;
        } catch (Exception e) {
            log.error("查询用户异常", e);
            return null;
        }
    }

    @Override
    public UpmpUserInfoVO findDetail(String userId) {
        LambdaQueryWrapper<UpmpUserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UpmpUserInfo::getId, userId);
        try {
            UpmpUserInfo user = this.getOne(queryWrapper);
            UpmpUserInfoVO userVo = new UpmpUserInfoVO();
            if (user != null) {

                BeanUtils.copyProperties(user,userVo);
                //
                if (!StringUtils.isEmpty(userVo.getOrgCode())) {
                    UpmpOrganization org = null;
                    org = upmpOrganizationService.getOrgByCode(userVo.getOrgCode(),userVo.getInstId());
                    if (!ObjectUtils.isEmpty(org)) {
                        userVo.setOrgName(org.getOrgName());
                    }
                }
                //机构及下级机构
                String userOrgCodes = this.findUserOrgCodes(userVo.getOrgCode(),userVo.getInstId());
                userVo.setUserOrgCodes(GZIPUtils.compress(userOrgCodes));
                userVo.setUserOrgCodeArr(userOrgCodes.split(StringPool.COMMA));

                //角色
                List<UpmpUserRole> userRoles = upmpUserRoleService.list(new LambdaQueryWrapper<UpmpUserRole>()
                        .eq(UpmpUserRole::getUserId, user.getId()));
                List<String> roleIds = userRoles.stream().map(it -> String.valueOf(it.getRoleId())).collect(Collectors.toList());
                List<UpmpRole> roles = upmpRoleService.list(new LambdaQueryWrapper<UpmpRole>().in(UpmpRole::getId, roleIds));
                List<String> roleNames = roles.stream().map(UpmpRole::getRoleName).collect(Collectors.toList());
                userVo.setRoleId(String.join(",", roleIds));
                userVo.setRoleName(String.join(",", roleNames));
                userVo.setUserRoles(roles);
            }
            return userVo;
        } catch (Exception e) {
            log.error("查询用户异常", e);
            return null;
        }
    }

    @Override
    @Transactional
    public void updateLoginTime(UpmpUserInfo user) throws Exception {
        user.setLastLoginDate(DateUtil.getDateFormat(new Date(),DateUtil.DATE_PATTERN_EIGHT));

        this.baseMapper.update(user, new LambdaQueryWrapper<UpmpUserInfo>().eq(UpmpUserInfo::getId, user.getId()));

        // 重新将用户信息加载到 redis中
//        upmpCacheService.saveUser(user);
    }

    @Override
    @Transactional
    public void createUser(UpmpUserInfoVO user) throws Exception {
        // 创建用户
        UpmpUserInfoVO currUser = CommonUtils.getCurrentUser(upmpSysParamService);
        if(!currUser.isAdmin()&&!user.getInstId().equals(currUser.getInstId())){
            throw new RedpException("法人行信息错误！");
        }
        user.setCrtOrgId(currUser.getOrgCode());
        user.setOprId(currUser.getId());
        user.setCreateTime(DateUtil.getDateFormat(new Date(),DateUtil.FULL_TIME_WITH_MILL_SPLIT_PATTERN));
        user.setUserImagePath(UpmpUserInfo.DEFAULT_AVATAR);
        user.setLoginId(user.getLoginId().trim());
        user.setUserId(IdWorker.getIdStr(user));
        user.setUserInst(user.getInstId());
        user.setLoginPassword(HashUtil.encryptGm(user.getLoginId(), redpProperties.getDefaultPassword()));
        user.setTransPasswordSalt(user.getLoginId());
        UpmpUserInfo userInfo = new UpmpUserInfo();
        BeanUtils.copyProperties(user,userInfo);
        save(userInfo);

        // 保存用户角色
        String[] roles = user.getRoleId().split(StringPool.COMMA);
        setUserRoles(userInfo, roles);

        // 创建用户默认的个性化配置
        userConfigService.initDefaultUserConfig(String.valueOf(userInfo.getId()));

        // 将用户相关信息保存到 Redis中
//        upmpUserManager.loadUserRedisCache(user);

        // 同步流程引擎
//        sysWorkFlowService.saveUser(user.getUsername());
//        List<String> roleList = new ArrayList<>();
//        for (String id : roles) {
//            roleList.add(upmpRoleService.findById(id).getRoleName());
//        }
//        sysWorkFlowService.createMembership(user.getUsername(), roleList);
    }

    @Override
    @Transactional
    public void updateUser(UpmpUserInfoVO userVO) throws Exception {
        UpmpUserInfo user = this.baseMapper.selectById(userVO.getId());
        String loginId = userVO.getLoginId();
        String orgLoginId = user.getLoginId();

        BeanUtils.copyProperties(userVO,user);

        //如果修改了loginId，则会重置密码
        if(!loginId.equals(orgLoginId)){
            user.setLoginPassword(HashUtil.encryptGm(userVO.getLoginId(), redpProperties.getDefaultPassword()));
            user.setTransPasswordSalt(userVO.getLoginId());
        }

        // 更新用户
        UpmpUserInfoVO currUser = CommonUtils.getCurrentUser(upmpSysParamService);
        user.setLastOprId(currUser.getOrgCode());
//        user.setLoginPassword(null);
        user.setLastUpdateTime(DateUtil.getDateFormat(new Date(),DateUtil.FULL_TIME_WITH_MILL_SPLIT_PATTERN));
        updateById(user);

        upmpUserRoleMapper.delete(new LambdaQueryWrapper<UpmpUserRole>().eq(UpmpUserRole::getUserId, user.getId()));

        String[] roles = userVO.getRoleId().split(StringPool.COMMA);
        setUserRoles(user, roles);

        // 重新将用户信息，用户角色信息，用户权限信息 加载到 redis中
        upmpCacheService.saveUser(user.getId());
        upmpCacheService.saveRoles(user.getId());
        upmpCacheService.savePermissions(user.getId());

        // 同步流程引擎
//        List<String> roleList = new ArrayList<>();
//        for (String id : roles) {
//            roleList.add(upmpRoleService.findById(id).getRoleName());
//        }
//        sysWorkFlowService.createMembership(user.getUsername(), roleList);
    }

    @Override
    @Transactional
    public void deleteUsers(String[] userIds) throws Exception {
        // 同步流程引擎
        for (String userId : userIds) {
            UpmpUserInfo user = this.baseMapper.selectById(userId);
//            this.sysWorkFlowService.deleteUser(user.getUsername());
        }

        // 先删除相应的缓存
        this.upmpUserManager.deleteUserRedisCache(userIds);

        List<String> list = Arrays.asList(userIds);

        removeByIds(list);

        // 删除用户角色
        this.upmpUserRoleService.deleteUserRolesByUserId(userIds);
        // 删除用户个性化配置
        this.userConfigService.deleteByUserId(userIds);
    }

    @Override
    @Transactional
    public void updateProfile(UpmpUserInfo user) throws Exception {
        updateById(user);
        // 重新缓存用户信息
        upmpCacheService.saveUser(user.getLoginId());
    }

    @Override
    @Transactional
    public void updateAvatar(String userId, String avatar) throws Exception {
        UpmpUserInfo user = new UpmpUserInfo();
        user.setUserImagePath(avatar);

        this.baseMapper.update(user, new LambdaQueryWrapper<UpmpUserInfo>().eq(UpmpUserInfo::getId, userId));
        // 重新缓存用户信息
        upmpCacheService.saveUser(userId);
    }

    @Override
    @Transactional
    public void updatePassword(String username, String password) throws Exception {
        UpmpUserInfo user = new UpmpUserInfo();
        user.setLoginPassword(HashUtil.encryptGm(username, password));

        this.baseMapper.update(user, new LambdaQueryWrapper<UpmpUserInfo>().eq(UpmpUserInfo::getUserName, username));
        // 重新缓存用户信息
        upmpCacheService.saveUser(username);
    }

    @Override
    @Deprecated
    @Transactional
    public void regist(String username, String password) throws Exception {
        UpmpUserInfo user = new UpmpUserInfo();
        user.setLoginPassword(HashUtil.encryptGm(username, password));
        user.setLoginId(username);
        user.setCreateTime(DateUtil.getDateFormat(new Date(),DateUtil.FULL_TIME_WITH_MILL_SPLIT_PATTERN));
//        user.setStatus(UpmpUserInfo.STATUS_VALID);
        user.setUserSex(UpmpUserInfo.SEX_UNKNOW);
        user.setUserImagePath(UpmpUserInfo.DEFAULT_AVATAR);
        user.setNickName("注册用户");
        this.save(user);

        UpmpUserRole ur = new UpmpUserRole();
        ur.setUserId(user.getId());
        ur.setRoleId("2"); // 注册用户角色 ID
        this.upmpUserRoleMapper.insert(ur);

        // 创建用户默认的个性化配置
        userConfigService.initDefaultUserConfig(String.valueOf(user.getId()));
        // 将用户相关信息保存到 Redis中
//        upmpUserManager.loadUserRedisCache(user);

    }

    @Override
    @Transactional
    public void resetPassword(String[] ids) throws Exception {
        for (String id : ids) {

            UpmpUserInfo user = this.baseMapper.selectById(id);
            user.setLoginPassword(HashUtil.encryptGm(user.getLoginId(), redpProperties.getDefaultPassword()));

            this.baseMapper.update(user, new LambdaQueryWrapper<UpmpUserInfo>().eq(UpmpUserInfo::getId, id));
            // 重新将用户信息加载到 redis中
            upmpCacheService.saveUser(id);
        }

    }

    @Override
    public List<UpmpUserInfo> getAllUsers() {
        return this.baseMapper.selectList(new QueryWrapper<>());
    }

    private void setUserRoles(UpmpUserInfo user, String[] roles) {
        Arrays.stream(roles).forEach(roleId -> {
            UpmpUserRole ur = new UpmpUserRole();
            ur.setUserId(user.getId());
            ur.setRoleId(roleId);
            ur.setInstId(user.getInstId());
            this.upmpUserRoleMapper.insert(ur);
        });
    }

    @Override
    public UpmpUserInfoVO findUpmpUserInfoVO(String instId,String userType,String loginId)throws RedpException {
//        return baseMapper.selectOne(new LambdaQueryWrapper<UpmpUserInfo>().eq(UpmpUserInfo::getUsername, username));
        List<UpmpUserInfo> list = Lists.newArrayList();
        if(UserTypeEnum.UPMP.getType().equals(userType)){//内管直接用登录账户
            list = baseMapper.findUpmpUserInfo(instId,loginId,UserStatusEnum.NORMAL.getType());
        }else if(UserTypeEnum.BSPS.getType().equals(userType)){//商户服务
            list = baseMapper.findBspsUserInfo(instId,loginId);
        }else if(UserTypeEnum.THIRD.getType().equals(userType)){//第三方应用
            list = baseMapper.findThirdUserInfo(instId,loginId);
        }
        if(CollectionUtils.isNotEmpty(list)){
            UpmpUserInfoVO vo = this.findDetail(list.get(0).getId());
            return vo;
        }
        return null;
    }

    @Override
    public UpmpUserInfo findUpmpUserInfo(String instId,String userType,String loginId)throws RedpException {
//        return baseMapper.selectOne(new LambdaQueryWrapper<UpmpUserInfo>().eq(UpmpUserInfo::getUsername, username));
        List<UpmpUserInfo> list = Lists.newArrayList();
        if(UserTypeEnum.UPMP.getType().equals(userType)){//内管直接用登录账户
            list = baseMapper.findUpmpUserInfo(instId,loginId, UserStatusEnum.NORMAL.getType());
        }else if(UserTypeEnum.BSPS.getType().equals(userType)){//商户服务
            list = baseMapper.findBspsUserInfo(instId,loginId);
        }else if(UserTypeEnum.THIRD.getType().equals(userType)){//第三方应用
            list = baseMapper.findThirdUserInfo(instId,loginId);
        }
        if(CollectionUtils.isNotEmpty(list)){
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据机构id获取机构编码及下级机构编码，组成以逗号分隔的字符串
     *
     * @param orgCode
     * @return
     */
    @Override
    public String findUserOrgCodes(String orgCode, String instId) throws RedpException {
        StringBuffer orgcodes = new StringBuffer();
        //根据机构号和法人行号查询机构信息
        UpmpOrganization org = upmpOrganizationService.getOrgByCode(orgCode, instId);
        orgcodes.append(org.getOrgCode());
        //把当前机构号作为上级机构号，根据上级机构号+法人行号查询下级机构号列表
        List<UpmpOrganization> orgs = upmpOrganizationService.getOrgListByParentCode(org.getOrgCode(), instId);
        if (null != orgs && orgs.size() > 0) {
            Iterator<UpmpOrganization> itorg = orgs.iterator();
            while (itorg.hasNext()) {
                UpmpOrganization organization = (UpmpOrganization) itorg.next();
                orgcodes.append(StringPool.COMMA).append(findUserOrgCodes(organization.getOrgCode(), instId));
            }
        }
        return orgcodes.toString();
    }

    @Override
    public List<UpmpUserInfo> queryUserByLoginId(String instId, String loginId) {
        return this.baseMapper.findUpmpUserInfo(instId,loginId,"");
    }
}
